﻿/*
 * Summary:
 *   The SportsStore class holds details of sports items
 *   
 * History:
 *   Date           Author      Changes
 *   18/10/2010     YIWEI YU    Created
 *   23/10/2010     YIWEI YU    Indexer integrated, not tested
 */

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AcmeSportsStore
{
    class SportsStore
    {
        /*
         * <remarks>
         *  items are stored and maintained by indexers
         *  because each indexer is actually an array
         *  of references to items
         * </remarks>
         */

        protected SportsItemIndexerById mIndexerById 
            = new SportsItemIndexerById();

        protected SportsItemIndexerByName mIndexerByName
            = new SportsItemIndexerByName();

        protected SportsItemIndexerByDescription mIndexerByDesc
            = new SportsItemIndexerByDescription();

        protected SportsItemIndexerByPrice mIndexerByPrice
            = new SportsItemIndexerByPrice();

        public SportsStore()
        {
        }

        public int Count
        {
            get
            {
                return mIndexerById.Count;
            }
        }

        public SportsItem GetItemByIndexForId(int index)
        {
            return (SportsItem)mIndexerById[index];
        }

        public SportsItem GetItemByIndexForName(int index)
        {
            return (SportsItem)mIndexerByName[index];
        }

        public SportsItem GetItemByIndexForDescription(int index)
        {
            return (SportsItem)mIndexerByDesc[index];
        }

        public SportsItem GetItemByIndexForPrice(int index)
        {
            return (SportsItem)mIndexerByPrice[index];
        }

        /*
         * <remarks>
         *  item is a reference to an existing item in the 
         *  list or is equal to such an item
         *  this applies to all of the following 4 methods
         * </remarks>
         */
        public int GetIndexForId(SportsItem item)
        {
            return mIndexerById.GetIndex(item);
        }

        public int GetIndexForName(SportsItem item)
        {
            return mIndexerByName.GetIndex(item);
        }

        public int GetIndexForDescription(SportsItem item)
        {
            return mIndexerByDesc.GetIndex(item);
        }

        public int GetIndexForPrice(SportsItem item)
        {
            return mIndexerByDesc.GetIndex(item);
        }

        public int GetIndexForIdById(string id)
        {
            /*
             * this is a just a temporary object for the 
             * searching to compare against
             */
            SportsItem dummy = new SportsItem(id, "", "", 0);

            return mIndexerById.GetIndex(dummy);
        }

        /*
         * get all the indices to objects that have
         * a name equal to the specified name
         */
        public bool GetIndicesForNameByName(string name, out int first,
            out int count)
        {
            SportsItem dummy = new SportsItem("", name, "", 0);

            return mIndexerByName.GetIndices(dummy, 
                out first, out count);
        }

        /*
         * get all the indices to objects that have
         * a description equal to the specified description
         */
        public bool GetIndicesForDescByDesc(string desc, 
            out int first, out int count)
        {
            SportsItem dummy = new SportsItem("", "", desc, 0);

            return mIndexerByDesc.GetIndices(dummy,
                out first, out count);
        }

        /*
         * get all the indices to objects that have
         * a price equal to the specified price
         */
        public bool GetIndicesForNameByPrice(int price,
            out int first, out int count)
        {
            SportsItem dummy = new SportsItem("", "", "", price);

            return mIndexerByPrice.GetIndices(dummy,
                out first, out count);
        }

        public void Clear()
        {
            mIndexerById.Clear();
            mIndexerByName.Clear();
            mIndexerByDesc.Clear();
            mIndexerByPrice.Clear();
        }

        public bool AddItem(SportsItem item)
        {
            int index = mIndexerById.Add(item);
            
            if (index < 0)
            {   /* already exists */
                return false;
            }

            /*
             * since it is accepted by id indexer
             * it should be accepted by all the
             * other indexers
             */
            mIndexerByName.Add(item);

            mIndexerByDesc.Add(item);

            mIndexerByPrice.Add(item);

            return true;
        }

        public bool RemoveItemById(string id)
        {
            int index = this.GetIndexForIdById(id);
            if (index < 0)
            {   /* not found */
                return false;
            }

            /*
             * retrieve the actual object to be removed
             */
            SportsItem objToRemove = (SportsItem)mIndexerById[index];
            mIndexerById.RemoveAt(index);

            /*
             * process the other three indexers
             */
            index = mIndexerByName.GetIndex(objToRemove);
            mIndexerByName.RemoveAt(index);

            index = mIndexerByDesc.GetIndex(objToRemove);
            mIndexerByDesc.RemoveAt(index);

            index = mIndexerByPrice.GetIndex(objToRemove);
            mIndexerByPrice.RemoveAt(index);

            return true;
        }

        public bool RemoveItemsByName(string name)
        {
            int first;
            int count;

            bool ok = this.GetIndicesForNameByName(name,
                out first, out count);
            if (!ok)
            {   /* not found */
                return false;
            }

            /*
             * 'i' goes through all the indices returned above
             */
            for (int i = first; count >= 0; count--, i++)
            {
                /*
                 * retrieve the actual object to be removed
                 */
                SportsItem objToRemove = (SportsItem)mIndexerByName[i];
                mIndexerById.RemoveAt(i);

                /*
                 * process the other three indexers
                 */
                int index = mIndexerById.GetIndex(objToRemove);
                mIndexerById.RemoveAt(index);

                index = mIndexerByDesc.GetIndex(objToRemove);
                mIndexerByDesc.RemoveAt(index);

                index = mIndexerByPrice.GetIndex(objToRemove);
                mIndexerByPrice.RemoveAt(index);

            }

            return true;
        }


        public bool RemoveItemsByDescription(string desc)
        {
            int first;
            int count;
            bool ok = this.GetIndicesForDescByDesc(desc,
                out first, out count);
            if (!ok)
            {   /* not found */
                return false;
            }

            /*
             * 'i' goes through all the indices returned above
             */
            for (int i = first; count >= 0; count--, i++)
            {
                /*
                 * retrieve the actual object to be removed
                 */
                SportsItem objToRemove = (SportsItem)mIndexerByDesc[i];
                mIndexerById.RemoveAt(i);

                /*
                 * process the other three indexers
                 */
                int index = mIndexerById.GetIndex(objToRemove);
                mIndexerById.RemoveAt(index);

                index = mIndexerByName.GetIndex(objToRemove);
                mIndexerByName.RemoveAt(index);

                index = mIndexerByPrice.GetIndex(objToRemove);
                mIndexerByPrice.RemoveAt(index);

            }

            return true;
        }

        public bool RemoveItemsByPrice(int price)
        {

            int first;
            int count;
            bool ok = this.GetIndicesForNameByPrice(price,
                out first, out count);
            if (!ok)
            {   /* not found */
                return false;
            }

            /*
             * 'i' goes through all the indices returned above
             */
            for (int i = first; count >= 0; count--, i++)
            {
                /*
                 * retrieve the actual object to be removed
                 */
                SportsItem objToRemove = (SportsItem)mIndexerByDesc[i];
                mIndexerById.RemoveAt(i);

                /*
                 * process the other three indexers
                 */
                int index = mIndexerById.GetIndex(objToRemove);
                mIndexerById.RemoveAt(index);

                index = mIndexerByName.GetIndex(objToRemove);
                mIndexerByName.RemoveAt(index);

                index = mIndexerByDesc.GetIndex(objToRemove);
                mIndexerByDesc.RemoveAt(index);
            }

            return true;
        }
    }
}
